package com.smart.community.property.mapper;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.smart.community.property.dto.PropertyFeeHouseholdDTO;
import com.smart.community.property.entity.PropertyFee;

/**
 * 物业费用数据访问层
 * 
 * @author Wu.Liang
 * @since 2024-12-19
 */
@Mapper
public interface PropertyFeeMapper extends BaseMapper<PropertyFee> {
    
    // 编译时常量 - 用于@Select注解
    int DELETED_NOT = 0;  // 未删除状态
    
    /**
     * 根据账单号查询账单
     * 
     * @param billNo 账单号
     * @return 账单信息
     */
    PropertyFee selectByBillNo(@Param("billNo") String billNo);
    
    /**
     * 根据房户ID和计费月份查询账单
     * 
     * @param householdId 房户ID
     * @param billingMonth 计费月份
     * @return 账单信息
     */
    PropertyFee selectByHouseholdIdAndBillingMonth(@Param("householdId") Long householdId,
                                                   @Param("billingMonth") String billingMonth);
    
    /**
     * 分页查询物业费账单
     * 
     * @param communityId 社区ID
     * @param status 状态
     * @param billingMonth 计费月份
     * @return 账单列表
     */
    List<PropertyFee> selectPropertyFeePage(@Param("communityId") Long communityId, 
                                           @Param("status") Integer status,
                                           @Param("billingMonth") String billingMonth);
    
    /**
     * 根据用户ID查询未缴费物业费账单
     * 
     * @param userId 用户ID
     * @return 未缴费账单列表
     */
    List<PropertyFee> selectUnpaidPropertyFeesByUserId(@Param("userId") Long userId);
    
    /**
     * 查询逾期物业费账单
     * 
     * @param communityId 社区ID
     * @param dueDate 到期日期
     * @return 逾期账单列表
     */
    List<PropertyFee> selectOverduePropertyFees(@Param("communityId") Long communityId,
                                               @Param("dueDate") LocalDate dueDate);
    
    /**
     * 更新物业费支付状态
     * 
     * @param id 账单ID
     * @param status 支付状态（0-未支付，1-已支付，2-逾期，3-部分支付）
     * @param paidAmount 支付金额
     * @param paymentMethod 支付方式（1-现金，2-微信，3-支付宝，4-银行卡）
     * @param paymentTime 支付时间
     * @return 更新结果
     */
    int updatePaymentStatus(@Param("id") Long id,
                           @Param("status") Integer status,
                           @Param("paidAmount") BigDecimal paidAmount,
                           @Param("paymentMethod") Integer paymentMethod,
                           @Param("paymentTime") LocalDateTime paymentTime);
    
    /**
     * 批量生成物业费账单
     * 
     * @param communityId 社区ID
     * @param billingPeriod 计费周期
     * @param feeType 费用计费方式：0-按面积计费，1-固定费用
     * @param unitPrice 单价（按面积计费时使用）
     * @param fixedAmount 固定金额（固定费用时使用）
     * @param createBy 创建人ID
     * @param dueDate 到期日期
     * @return 生成的账单数量
     */
    int batchGeneratePropertyFees(@Param("communityId") Long communityId,
                                 @Param("billingPeriod") String billingPeriod,
                                 @Param("feeType") Integer feeType,
                                 @Param("unitPrice") BigDecimal unitPrice,
                                 @Param("fixedAmount") BigDecimal fixedAmount,
                                 @Param("createBy") Long createBy,
                                 @Param("dueDate") LocalDate dueDate);
    
    /**
     * 批量生成物业费账单（按时间段生成一份总费用单）
     * 
     * @param communityId 社区ID
     * @param billingPeriod 计费周期（时间段格式：2025-08 ~ 2025-11）
     * @param feeType 费用计费方式：0-按面积计费，1-固定费用
     * @param unitPrice 单价（按面积计费时使用）
     * @param fixedAmount 固定金额（固定费用时使用）
     * @param createBy 创建人ID
     * @param dueDate 到期日期
     * @param monthCount 月份数量
     * @param remark 备注
     * @return 生成的账单数量
     */
    int batchGeneratePropertyFeesByRange(@Param("communityId") Long communityId,
                                        @Param("billingPeriod") String billingPeriod,
                                        @Param("feeType") Integer feeType,
                                        @Param("unitPrice") BigDecimal unitPrice,
                                        @Param("fixedAmount") BigDecimal fixedAmount,
                                        @Param("createBy") Long createBy,
                                        @Param("dueDate") LocalDate dueDate,
                                        @Param("monthCount") Integer monthCount,
                                        @Param("remark") String remark);
    
    /**
     * 查询需要生成物业费账单的房户信息（按时间段）
     * 
     * @param communityId 社区ID
     * @param billingPeriod 计费周期（时间段格式：2025-08 ~ 2025-11）
     * @param feeType 费用计费方式：0-按面积计费，1-固定费用
     * @return 房户信息列表
     */
    List<PropertyFeeHouseholdDTO> selectHouseholdsForPropertyFeeByRange(@Param("communityId") Long communityId,
                                                                        @Param("billingPeriod") String billingPeriod,
                                                                        @Param("feeType") Integer feeType);
    
    /**
     * 插入单条物业费账单
     * 
     * @param propertyFee 物业费账单对象
     * @return 插入结果
     */
    int insertPropertyFee(PropertyFee propertyFee);
    
    /**
     * 批量更新催缴状态
     * 
     * @param billIds 账单ID列表
     * @return 更新结果
     */
    int batchUpdateReminderStatus(@Param("billIds") List<Long> billIds);
    
    /**
     * 根据社区ID统计费用信息
     * 
     * @param communityId 社区ID
     * @return 统计信息
     */
    Map<String, Object> getStatisticsByCommunityId(@Param("communityId") Long communityId);
    
    /**
     * 获取物业费统计信息
     * 
     * @param communityId 社区ID
     * @param year 年份
     * @return 统计信息
     */
    Map<String, Object> selectPropertyFeeStatistics(@Param("communityId") Long communityId,
                                                   @Param("year") Integer year);
    
    /**
     * 获取月度物业费趋势统计
     * 
     * @param communityId 社区ID
     * @param year 年份
     * @return 趋势统计
     */
    List<Map<String, Object>> selectMonthlyTrend(@Param("communityId") Long communityId,
                                                @Param("year") Integer year);
    
    /**
     * 获取社区物业费汇总统计
     * 
     * @param communityId 社区ID
     * @return 汇总统计
     */
    List<Map<String, Object>> selectCommunitySummary(@Param("communityId") Long communityId);
    
    /**
     * 统计指定时间范围内的收入
     * 
     * @param communityId 社区ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 收入统计
     */
    List<Map<String, Object>> getIncomeStatistics(@Param("communityId") Long communityId,
                                                 @Param("startDate") LocalDate startDate,
                                                 @Param("endDate") LocalDate endDate);
    
    /**
     * 根据房户ID查询费用记录
     * 
     * @param householdId 房户ID
     * @return 费用记录列表
     */
    List<PropertyFee> getFeesByHouseholdId(@Param("householdId") Long householdId);
    
    /**
     * 根据费用期间查询费用
     * 
     * @param billingPeriod 计费期间
     * @return 费用记录列表
     */
    List<PropertyFee> getFeesByPeriod(@Param("billingPeriod") String billingPeriod);
    
    /**
     * 根据用户ID查询未缴费用
     * 
     * @param userId 用户ID
     * @return 未缴费用列表
     */
    List<PropertyFee> getUnpaidFeesByUserId(@Param("userId") Long userId);
    
    /**
     * 查询逾期费用
     * 
     * @return 逾期费用列表
     */
    List<PropertyFee> getOverdueFees();
    
    /**
     * 查询用户在指定时间范围内的缴费记录
     * 
     * @param userId 用户ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 缴费记录列表
     */
    List<PropertyFee> getPaymentRecords(@Param("userId") Long userId,
                                       @Param("startDate") LocalDate startDate,
                                       @Param("endDate") LocalDate endDate);
    
    /**
     * 根据计费期间查询物业费
     * 
     * @param billingPeriod 计费期间
     * @return 物业费列表
     */
    @Select("SELECT * FROM sc_property_fee " +
            "WHERE billing_period = #{billingPeriod} AND deleted = " + DELETED_NOT + " " +
            "ORDER BY create_time DESC")
    List<PropertyFee> selectByBillingPeriod(@Param("billingPeriod") String billingPeriod);
    
    /**
     * 根据社区ID查询物业费
     * 
     * @param communityId 社区ID
     * @return 物业费列表
     */
    @Select("SELECT * FROM sc_property_fee " +
            "WHERE community_id = #{communityId} AND deleted = " + DELETED_NOT)
    List<PropertyFee> selectByCommunityId(@Param("communityId") Long communityId);
    
    /**
     * 根据日期范围查询已缴费记录
     * 
     * @param communityId 社区ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 已缴费记录列表
     */
    @Select("SELECT * FROM sc_property_fee " +
            "WHERE community_id = #{communityId} AND payment_status = 1 " +
            "AND payment_time BETWEEN #{startDate} AND #{endDate} " +
            "ORDER BY payment_time DESC")
    List<PropertyFee> selectPaidFeesByDateRange(@Param("communityId") Long communityId,
                                               @Param("startDate") LocalDate startDate,
                                               @Param("endDate") LocalDate endDate);
    
    /**
     * 根据房户ID查询物业费
     * 
     * @param householdId 房户ID
     * @return 物业费列表
     */
    @Select("SELECT * FROM sc_property_fee " +
            "WHERE household_id = #{householdId} AND deleted = " + DELETED_NOT + " " +
            "ORDER BY due_date ASC")
    List<PropertyFee> selectByHouseholdId(@Param("householdId") Long householdId);
    
    /**
     * 查询逾期费用
     * 
     * @return 逾期费用列表
     */
    @Select("SELECT * FROM sc_property_fee " +
            "WHERE payment_status = 0 AND due_date < NOW() AND deleted = " + DELETED_NOT + " " +
            "ORDER BY due_date ASC")
    List<PropertyFee> selectOverdueFees();
    
    /**
     * 根据用户ID查询已缴费记录
     * 
     * @param userId 用户ID
     * @return 已缴费记录列表
     */
    @Select("SELECT * FROM sc_property_fee " +
            "WHERE user_id = #{userId} AND payment_status = 1 " +
            "ORDER BY payment_time DESC")
    List<PropertyFee> selectPaidFeesByUserId(@Param("userId") Long userId);
    
    /**
     * 根据用户ID查询未缴费记录
     * 
     * @param userId 用户ID
     * @return 未缴费记录列表
     */
    @Select("SELECT * FROM sc_property_fee " +
            "WHERE user_id = #{userId} AND payment_status = 0 AND deleted = " + DELETED_NOT + " " +
            "ORDER BY due_date ASC")
    List<PropertyFee> selectUnpaidFeesByUserId(@Param("userId") Long userId);
    
    /**
     * 查询费用类型统计
     * 
     * @param communityId 社区ID
     * @return 费用类型统计
     */
    @Select("SELECT " +
            "fee_type as feeType, " +
            "COUNT(*) as totalCount, " +
            "COUNT(CASE WHEN payment_status = 1 THEN 1 END) as paidCount, " +
            "COUNT(CASE WHEN payment_status = 0 THEN 1 END) as unpaidCount, " +
            "COALESCE(SUM(amount), 0) as totalAmount, " +
            "COALESCE(SUM(CASE WHEN payment_status = 1 THEN payment_amount ELSE 0 END), 0) as paidAmount " +
            "FROM sc_property_fee " +
            "WHERE community_id = #{communityId} AND deleted = " + DELETED_NOT + " " +
            "GROUP BY fee_type")
    List<Map<String, Object>> selectFeeTypeStatistics(@Param("communityId") Long communityId);
    
    /**
     * 查询收入统计
     * 
     * @param communityId 社区ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 收入统计
     */
    @Select("SELECT " +
            "COALESCE(SUM(payment_amount), 0) as totalIncome, " +
            "COUNT(*) as paidCount, " +
            "AVG(payment_amount) as avgPayment " +
            "FROM sc_property_fee " +
            "WHERE community_id = #{communityId} AND payment_status = 1 " +
            "AND payment_time BETWEEN #{startDate} AND #{endDate}")
    Map<String, Object> selectIncomeStatistics(@Param("communityId") Long communityId,
                                              @Param("startDate") LocalDate startDate,
                                              @Param("endDate") LocalDate endDate);
    
    /**
     * 分页查询用户物业费账单（去重版本）
     * 按房户ID、计费周期、费用类型去重，符合ONLY_FULL_GROUP_BY模式
     * 
     * @param householdIds 房户ID列表
     * @param paymentStatus 缴费状态
     * @param feeType 费用类型
     * @param billingPeriod 计费周期
     * @param offset 偏移量
     * @param limit 限制数量
     * @return 物业费账单列表
     */
    List<PropertyFee> selectMyPropertyFeesPage(@Param("householdIds") List<Long> householdIds,
                                              @Param("paymentStatus") Integer paymentStatus,
                                              @Param("feeType") Integer feeType,
                                              @Param("billingPeriod") String billingPeriod,
                                              @Param("offset") Integer offset,
                                              @Param("limit") Integer limit);
    
    /**
     * 统计用户物业费账单总数（去重版本）
     * 按房户ID、计费周期、费用类型去重，符合ONLY_FULL_GROUP_BY模式
     * 
     * @param householdIds 房户ID列表
     * @param paymentStatus 缴费状态
     * @param feeType 费用类型
     * @param billingPeriod 计费周期
     * @return 总数
     */
    Long countMyPropertyFees(@Param("householdIds") List<Long> householdIds,
                            @Param("paymentStatus") Integer paymentStatus,
                            @Param("feeType") Integer feeType,
                            @Param("billingPeriod") String billingPeriod);
} 